transient Object[] elements; // non-private to simplify nested class access
/** * The index of the element at the head of the deque (which is the * element that would be removed by remove() or pop()); or an * arbitrary number equal to tail if the deque is empty. */ transient int head;
/** * The index at which the next element would be added to the tail * of the deque (via addLast(E), add(E), or push(E)). */ transient int tail;
public ArrayDeque() { elements = new Object[16]; } public ArrayDeque(int numElements) { allocateElements(numElements); } public ArrayDeque(Collection<? extends E> c) { allocateElements(c.size()); addAll(c); }
private void allocateElements(int numElements) { elements = new Object[calculateSize(numElements)]; }
private static int calculateSize(int numElements) { int initialCapacity = MIN_INITIAL_CAPACITY; // Find the best power of two to hold elements. // Tests "<=" because arrays aren't kept full. if (numElements >= initialCapacity) { initialCapacity = numElements; initialCapacity |= (initialCapacity >>> 1); initialCapacity |= (initialCapacity >>> 2); initialCapacity |= (initialCapacity >>> 4); initialCapacity |= (initialCapacity >>> 8); initialCapacity |= (initialCapacity >>> 16); initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements } return initialCapacity; }
普通的方法
add 使用 addLast 在末尾追加元素
1 2 3 4
public boolean add(E e) { addLast(e); return true; }
public void addLast(E e) { if (e == null) throw new NullPointerException(); elements[tail] = e; if ( (tail = (tail + 1) & (elements.length - 1)) == head) doubleCapacity(); }
doubleCapacity 函数,新数组的大小为两倍,使用 System.arraycopy 函数复制,效率极高。因为 head 不一定为零,所以在扩容的时候,需要恢复head = 0;这里我们应该推测出整个数组都是存储数据,为了方便删除数组而不移动元素,便使用了指针记录状态,这一实现必须要好好琢磨,下次面试别人的时候可以问一下别人,哈哈,有点小坏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
private void doubleCapacity() { assert head == tail; int p = head; int n = elements.length; int r = n - p; // number of elements to the right of p int newCapacity = n << 1; if (newCapacity < 0) throw new IllegalStateException("Sorry, deque too big"); Object[] a = new Object[newCapacity]; System.arraycopy(elements, p, a, 0, r); System.arraycopy(elements, 0, a, r, p); elements = a; head = 0; tail = n; }
public E pollFirst() { int h = head; @SuppressWarnings("unchecked") E result = (E) elements[h]; // Element is null if deque empty if (result == null) return null; elements[h] = null; // Must null out slot head = (h + 1) & (elements.length - 1); return result; }
public E pollLast() { int t = (tail - 1) & (elements.length - 1); @SuppressWarnings("unchecked") E result = (E) elements[t]; if (result == null) return null; elements[t] = null; tail = t; return result; }
其他的不涉及到删除,添加到操作就显得尤为简单了,直接获取,就不必多说了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public E getFirst() { @SuppressWarnings("unchecked") E result = (E) elements[head]; if (result == null) throw new NoSuchElementException(); return result; }
/** * @throws NoSuchElementException {@inheritDoc} */ public E getLast() { @SuppressWarnings("unchecked") E result = (E) elements[(tail - 1) & (elements.length - 1)]; if (result == null) throw new NoSuchElementException(); return result; }
pop 根据先进先出,pop 应该移除队首的元素,注意,这里会抛出异常,如果队首为空的话
1 2 3 4 5
* @throws NoSuchElementException {@inheritDoc} */ public E pop() { return removeFirst(); }